#include "Eventfd.hpp"

#include <cstdint>
#include <sys/eventfd.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <string.h>

#include <iostream>

using std::cout;
using std::endl;


Eventfd::Eventfd(EventCallback && cb)
: _isLooping(false)
, _eventfd(createEventfd())
, _epfd(createEpollFd())
, _cb(std::move(cb))
{
    cout << "_eventfd:" << _eventfd << endl;
    cout << "_epfd:" << _epfd << endl;
}

Eventfd::~Eventfd()
{
    close(_eventfd);
    close(_epfd);
}

void Eventfd::start()
{
    _isLooping = true;
    addEpollReadFd();
    struct epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    int nready = 0;
    while(_isLooping) {
        /* cout << "enter epoll loop" << endl; */
        nready = epoll_wait(_epfd, &ev, 1, 5000);

        for(int i = 0; i < nready; ++i) {
            if(_eventfd == ev.data.fd) {
                //收到另一个线程的通知了
                handleRead();
                if(_cb) {
                    _cb();
                }
            }
        }
    }
}

void Eventfd::stop()
{
    _isLooping = false;
}

//每一次调用就是往内核计数器上加1
void Eventfd::wakeup()
{
    uint64_t one = 1;
    int ret = write(_eventfd, &one, sizeof(one));
    if(ret != sizeof(one)) {
        perror("write");
    }
}



int Eventfd::createEventfd()
{
    int fd = eventfd(0, 0);
    if(fd < 0) {
        perror("eventfd");
    }
    return fd;
}

int Eventfd::createEpollFd()
{
    int fd = epoll_create1(0);
    if(fd < 0) {
        perror("epoll_create1");
    }
    return fd;
}

void Eventfd::addEpollReadFd()
{
    struct epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.data.fd = _eventfd;
    ev.events = EPOLLIN;
    int ret = epoll_ctl(_epfd, EPOLL_CTL_ADD, _eventfd, &ev);
    if(ret < 0) {
        perror("epoll_ctl");
    }
}

//对读事件进行处理
void Eventfd::handleRead()
{
    uint64_t howmany = 0;
    int ret = read(_eventfd, &howmany, sizeof(howmany));
    if(ret != sizeof(howmany)) {
        perror("read");
    }
}

